package com.mojo.nio.channel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 抽象类选择器常用方法
 *
 * @author <a href="mailto:mojo_jj@163.com">Mojo</a>
 */
public class SelectorDemo {
    public static void main(String[] args) throws IOException {
        //1 创建channel
        ServerSocketChannel channel = ServerSocketChannel.open();
        channel.configureBlocking(false);
        channel.socket().bind(new InetSocketAddress(8080));
        //2 将channel注册进Selector

        Selector selector = Selector.open();
        channel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            //3 监听事件，直到一个事件到达
            int readyChannels = selector.select();

            if (readyChannels == 0) {
                continue;
            }
            //4 获取到达的事件
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                // 5 判断并处理
                if (key.isAcceptable()) {
                    // 处理连接事件
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);

                    // 将客户端通道注册到 Selector 并监听 OP_READ 事件
                    client.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    // 处理读事件
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = client.read(buffer);

                    if (bytesRead > 0) {
                        buffer.flip();
                        System.out.println("收到数据：" + new String(buffer.array(), 0, bytesRead));
                        // 将客户端通道注册到 Selector 并监听 OP_WRITE 事件
                        client.register(selector, SelectionKey.OP_WRITE);
                    } else if (bytesRead < 0) {
                        // 客户端断开连接
                        client.close();
                    }
                } else if (key.isWritable()) {
                    // 处理写事件
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.wrap("Hello, Client!".getBytes());
                    client.write(buffer);

                    // 将客户端通道注册到 Selector 并监听 OP_READ 事件
                    client.register(selector, SelectionKey.OP_READ);
                }

                keyIterator.remove();
            }
        }
    }
}
